//添加预算管理
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <ctime>
#include <limits>

using namespace std;

// 账单记录类
class BillRecord {
public:
    string date;        // 日期 (格式: YYYY-MM-DD)
    double amount;      // 金额
    string category;    // 类别
    string remark;      // 备注
    bool isIncome;      // true: 收入, false: 支出

    BillRecord(string d, double a, string c, string r, bool income)
        : date(d), amount(a), category(c), remark(r), isIncome(income) {}
};

// 账单管理系统类
class BillManagementSystem {
private:
    vector<BillRecord> records;         // 所有账单记录
    map<string, double> monthlyBudget;  // 月度预算 (key: "YYYY-MM", value: 预算金额)

    // 验证日期格式 (YYYY-MM-DD)
    bool isValidDate(const string& date) {
        if (date.length() != 10) return false;
        if (date[4] != '-' || date[7] != '-') return false;

        for (int i = 0; i < 10; i++) {
            if (i == 4 || i == 7) continue;
            if (!isdigit(date[i])) return false;
        }

        int year = stoi(date.substr(0, 4));
        int month = stoi(date.substr(5, 2));
        int day = stoi(date.substr(8, 2));

        if (month < 1 || month > 12) return false;
        if (day < 1 || day > 31) return false;

        // 简单的月份天数验证
        if ((month == 4 || month == 6 || month == 9 || month == 11) && day > 30) return false;
        if (month == 2) {
            bool isLeap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
            if ((isLeap && day > 29) || (!isLeap && day > 28)) return false;
        }

        return true;
    }

    // 获取当前月份 (YYYY-MM格式)
    string getCurrentMonth() {
        time_t now = time(0);
        tm* ltm = localtime(&now);
        stringstream ss;
        ss << (1900 + ltm->tm_year) << "-"
           << setw(2) << setfill('0') << (1 + ltm->tm_mon);
        return ss.str();
    }

    // 从日期中提取月份 (YYYY-MM格式)
    string extractMonth(const string& date) {
        return date.substr(0, 7);
    }

    // 显示记录列表
    void displayRecords(const vector<BillRecord>& recordsToDisplay, const string& title) {
        if (recordsToDisplay.empty()) {
            cout << "暂无" << title << "记录。" << endl;
            return;
        }

        cout << "\n=== " << title << " ===" << endl;
        cout << setw(12) << left << "日期"
             << setw(10) << "类型"
             << setw(12) << "金额"
             << setw(15) << "类别"
             << setw(20) << "备注" << endl;
        cout << string(70, '-') << endl;

        for (const auto& record : recordsToDisplay) {
            cout << setw(12) << left << record.date
                 << setw(10) << (record.isIncome ? "收入" : "支出")
                 << setw(12) << fixed << setprecision(2) << record.amount
                 << setw(15) << record.category
                 << setw(20) << record.remark << endl;
        }
        cout << endl;
    }

public:
    // 记录收入
    void recordIncome() {
        string date, category, remark;
        double amount;

        cout << "\n=== 记录收入 ===" << endl;

        // 输入日期
        cout << "请输入日期 (YYYY-MM-DD): ";
        cin >> date;
        if (!isValidDate(date)) {
            cout << "错误: 日期格式不正确！" << endl;
            return;
        }

        // 输入金额
        cout << "请输入金额: ";
        cin >> amount;
        if (amount <= 0) {
            cout << "错误: 金额必须为正数！" << endl;
            return;
        }

        cin.ignore(); // 清除输入缓冲区

        // 输入类别
        cout << "请输入类别 (如: 工资, 奖金等): ";
        getline(cin, category);

        // 输入备注
        cout << "请输入备注: ";
        getline(cin, remark);

        // 添加记录
        records.push_back(BillRecord(date, amount, category, remark, true));
        cout << "收入记录添加成功！" << endl;
    }

    // 记录支出
    void recordExpense() {
        string date, category, remark;
        double amount;

        cout << "\n=== 记录支出 ===" << endl;

        // 输入日期
        cout << "请输入日期 (YYYY-MM-DD): ";
        cin >> date;
        if (!isValidDate(date)) {
            cout << "错误: 日期格式不正确！" << endl;
            return;
        }

        // 输入金额
        cout << "请输入金额: ";
        cin >> amount;
        if (amount <= 0) {
            cout << "错误: 金额必须为正数！" << endl;
            return;
        }

        cin.ignore(); // 清除输入缓冲区

        // 输入类别
        cout << "请输入类别 (如: 餐饮, 交通, 购物等): ";
        getline(cin, category);

        // 输入备注
        cout << "请输入备注: ";
        getline(cin, remark);

        // 添加记录
        records.push_back(BillRecord(date, amount, category, remark, false));
        cout << "支出记录添加成功！" << endl;
    }

    // 账单展示
    void displayAllBills() {
        vector<BillRecord> incomeRecords, expenseRecords;

        // 分离收入和支出记录
        for (const auto& record : records) {
            if (record.isIncome) {
                incomeRecords.push_back(record);
            } else {
                expenseRecords.push_back(record);
            }
        }

        displayRecords(incomeRecords, "收入记录");
        displayRecords(expenseRecords, "支出记录");
    }

    // 账单查询
    void queryBills() {
        int choice;
        cout << "\n=== 账单查询 ===" << endl;
        cout << "1. 按日期查询" << endl;
        cout << "2. 按日期范围查询" << endl;
        cout << "3. 按类别查询" << endl;
        cout << "请选择查询方式: ";
        cin >> choice;

        vector<BillRecord> incomeResults, expenseResults;

        switch (choice) {
            case 1: { // 按日期查询
                string date;
                cout << "请输入查询日期 (YYYY-MM-DD): ";
                cin >> date;
                if (!isValidDate(date)) {
                    cout << "错误: 日期格式不正确！" << endl;
                    return;
                }

                for (const auto& record : records) {
                    if (record.date == date) {
                        if (record.isIncome) incomeResults.push_back(record);
                        else expenseResults.push_back(record);
                    }
                }
                break;
            }
            case 2: { // 按日期范围查询
                string startDate, endDate;
                cout << "请输入开始日期 (YYYY-MM-DD): ";
                cin >> startDate;
                cout << "请输入结束日期 (YYYY-MM-DD): ";
                cin >> endDate;

                if (!isValidDate(startDate) || !isValidDate(endDate)) {
                    cout << "错误: 日期格式不正确！" << endl;
                    return;
                }

                for (const auto& record : records) {
                    if (record.date >= startDate && record.date <= endDate) {
                        if (record.isIncome) incomeResults.push_back(record);
                        else expenseResults.push_back(record);
                    }
                }
                break;
            }
            case 3: { // 按类别查询
                string category;
                cin.ignore();
                cout << "请输入查询类别: ";
                getline(cin, category);

                for (const auto& record : records) {
                    if (record.category == category) {
                        if (record.isIncome) incomeResults.push_back(record);
                        else expenseResults.push_back(record);
                    }
                }
                break;
            }
            default:
                cout << "错误: 无效的选择！" << endl;
                return;
        }

        displayRecords(incomeResults, "查询结果 - 收入");
        displayRecords(expenseResults, "查询结果 - 支出");
    }

    // 设置预算
    void setBudget() {
        string month;
        double budget;

        cout << "\n=== 设置月度预算 ===" << endl;
        cout << "请输入月份 (YYYY-MM): ";
        cin >> month;

        // 简单验证月份格式
        if (month.length() != 7 || month[4] != '-') {
            cout << "错误: 月份格式不正确！" << endl;
            return;
        }

        cout << "请输入预算金额: ";
        cin >> budget;
        if (budget < 0) {
            cout << "错误: 预算金额不能为负数！" << endl;
            return;
        }

        monthlyBudget[month] = budget;
        cout << month << " 的预算设置为: " << fixed << setprecision(2) << budget << " 元" << endl;
    }

    // 显示剩余预算
    void showRemainingBudget() {
        string currentMonth = getCurrentMonth();
        auto it = monthlyBudget.find(currentMonth);

        if (it == monthlyBudget.end()) {
            cout << "当前月份 (" << currentMonth << ") 未设置预算。" << endl;
            return;
        }

        double budget = it->second;
        double totalExpense = 0.0;

        // 计算当前月份的总支出
        for (const auto& record : records) {
            if (!record.isIncome && extractMonth(record.date) == currentMonth) {
                totalExpense += record.amount;
            }
        }

        double remaining = budget - totalExpense;
        cout << "\n=== " << currentMonth << " 预算情况 ===" << endl;
        cout << "预算总额: " << fixed << setprecision(2) << budget << " 元" << endl;
        cout << "已支出: " << totalExpense << " 元" << endl;
        cout << "剩余预算: " << remaining << " 元" << endl;

        if (remaining < 0) {
            cout << "警告: 已超出预算 " << -remaining << " 元！" << endl;
        }
    }

    // 月度统计
    void monthlyStatistics() {
        string month;
        cout << "\n=== 月度统计 ===" << endl;
        cout << "请输入月份 (YYYY-MM): ";
        cin >> month;

        // 简单验证月份格式
        if (month.length() != 7 || month[4] != '-') {
            cout << "错误: 月份格式不正确！" << endl;
            return;
        }

        double totalIncome = 0.0, totalExpense = 0.0;
        map<string, double> categoryExpense;  // 各类别支出统计

        for (const auto& record : records) {
            if (extractMonth(record.date) == month) {
                if (record.isIncome) {
                    totalIncome += record.amount;
                } else {
                    totalExpense += record.amount;
                    categoryExpense[record.category] += record.amount;
                }
            }
        }

        cout << "\n=== " << month << " 月度统计 ===" << endl;
        cout << "总收入: " << fixed << setprecision(2) << totalIncome << " 元" << endl;
        cout << "总支出: " << totalExpense << " 元" << endl;
        cout << "净收入: " << (totalIncome - totalExpense) << " 元" << endl;

        if (!categoryExpense.empty()) {
            cout << "\n=== 支出类别统计 ===" << endl;
            for (const auto& item : categoryExpense) {
                cout << setw(15) << left << item.first << ": "
                     << setw(10) << fixed << setprecision(2) << item.second << " 元" << endl;
            }
        }
    }

    // 显示菜单
    void showMenu() {
        cout << "\n=== 个人账单管理系统 ===" << endl;
        cout << "1. 记录收入" << endl;
        cout << "2. 记录支出" << endl;
        cout << "3. 账单展示" << endl;
        cout << "4. 账单查询" << endl;
        cout << "5. 设置月度预算" << endl;
        cout << "6. 显示剩余预算" << endl;
        cout << "7. 月度统计" << endl;
        cout << "8. 退出系统" << endl;
        cout << "请选择操作 (1-8): ";
    }

    // 运行系统
    void run() {
        int choice;

        while (true) {
            showMenu();
            cin >> choice;

            // 处理输入错误
            if (cin.fail()) {
                cin.clear();
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
                cout << "错误: 请输入有效的数字！" << endl;
                continue;
            }

            switch (choice) {
                case 1:
                    recordIncome();
                    break;
                case 2:
                    recordExpense();
                    break;
                case 3:
                    displayAllBills();
                    break;
                case 4:
                    queryBills();
                    break;
                case 5:
                    setBudget();
                    break;
                case 6:
                    showRemainingBudget();
                    break;
                case 7:
                    monthlyStatistics();
                    break;
                case 8:
                    cout << "感谢使用个人账单管理系统，再见！" << endl;
                    return;
                default:
                    cout << "错误: 无效的选择，请重新输入！" << endl;
                    break;
            }
        }
    }
};

int main() {
    BillManagementSystem system;
    system.run();
    return 0;
}
